package com.device.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.device.domain.CabinetSlot;
import com.device.domain.PowerBank;
import com.device.domain.dto.CabinetAddUpdateDto;
import com.device.domain.dto.CabinetDto;
import com.device.domain.entity.Cabinet;
import com.device.domain.vo.CabinetSlotBankVo;
import com.device.domain.vo.CabinetVo;
import com.device.mapper.CabinetMapper;
import com.device.mapper.CabinetSlotMapper;
import com.device.service.ICabinetService;
import com.device.service.IPowerBankService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class CabinetServiceImpl extends ServiceImpl<CabinetMapper, Cabinet>
        implements ICabinetService {

    @Autowired
    private CabinetMapper cabinetMapper;

    @Autowired
    private CabinetSlotMapper cabinetSlotMapper;

    @Autowired
    IPowerBankService powerBankService;

    @Autowired
    RedisTemplate<Object, Object> redisTemplate;



    /**
     * 柜机管理查询
     */
    @Override
    @Cacheable(
            value = "selectCabinetList",
            key = "#cabinetDto.pageNum + '-' + #cabinetDto.pageSize + '-' + (#cabinetDto.name?:'')",
            unless = "#result == null"
    )
    public PageInfo<CabinetVo> selectCabinetList(CabinetDto cabinetDto) {

        PageHelper.startPage(cabinetDto.getPageNum(), cabinetDto.getPageSize());
        List<CabinetVo> cabinets = cabinetMapper.selectCabinetList(cabinetDto);
        PageInfo<CabinetVo> pageInfo = new PageInfo<>(cabinets);
        pageInfo.setPageNum(cabinetDto.getPageNum());
        pageInfo.setPageSize(cabinetDto.getPageSize());

        return pageInfo;
    }


    /**
     * 获取充电宝柜机全部详细信息
     */
    @Override
    public Map<String, Object> getAllInfo(Long id) {
        //1 获取柜机信息
        Cabinet cabinet = getById(id);

        //2 查询插槽信息
        List<CabinetSlot> cabinetSlotList = cabinetSlotMapper.selectList(new LambdaQueryWrapper<CabinetSlot>().eq(CabinetSlot::getCabinetId, cabinet.getId()));

        //3 获取可用充电宝id列表
        List<Long> powerBankIdList = cabinetSlotList.stream().filter(item -> null != item.getPowerBankId()).map(CabinetSlot::getPowerBankId).toList();

        if(!CollectionUtils.isEmpty(powerBankIdList)) {
            //4 根据充电宝id列表查询充电宝信息
            List<PowerBank> powerBankList = powerBankService.listByIds(powerBankIdList);
            //5 转换成map
            Map<Long, PowerBank> powerBankIdToPowerBankMap = powerBankList.stream().collect(Collectors.toMap(PowerBank::getId, PowerBank -> PowerBank));
            //插入集合
            cabinetSlotList.forEach(item -> item.setPowerBank(powerBankIdToPowerBankMap.get(item.getPowerBankId())));
        }

        return Map.of("cabinet", cabinet, "cabinetSlotList", cabinetSlotList);
    }



    /**
     * 柜机详情
     */
    @Override
    @Cacheable(
            value = "cabinetDetail",
            key = "#id",
            unless = "#result == null || #result.isEmpty()"
    )
    public List<CabinetSlotBankVo> getCabinet(Integer id) {
        return cabinetMapper.getCabinet(id);
    }


    /**
     * 搜索未使用柜机
     */
    @Override
    @Cacheable(
            value = "noUseCabinetList",
            key = "#keyword",
            unless = "#result == null || #result.isEmpty()"
    )
    public List<Cabinet> searchNoUseList(String keyword) {
        LambdaQueryWrapper<Cabinet> lambdaQuery = new LambdaQueryWrapper<>();
        lambdaQuery.like(Cabinet::getName, keyword)
                .eq(Cabinet::getStatus, "0");
        return cabinetMapper.selectList(lambdaQuery);
    }
    /**
     * 新增柜机
     */
    @Override
    @Caching(
            evict = {
                    @CacheEvict(value = "selectCabinetList", allEntries = true),
                    @CacheEvict(value = "noUseCabinetList", allEntries = true)
            }
    )
    public void cabinetSave(CabinetAddUpdateDto cabinetAddUpdateDto) {
        Cabinet cabinets = BeanUtil.copyProperties(cabinetAddUpdateDto, Cabinet.class);
        cabinetMapper.insert(cabinets);
    }
    /**
     * 修改柜机
     */
    @Override
    @Caching(
            evict = {
                    @CacheEvict(value = "selectCabinetList", allEntries = true),
                    @CacheEvict(value = "cabinetAllInfo", key = "#cabinetAddUpdateDto.id"),
                    @CacheEvict(value = "cabinetDetail", key = "#cabinetAddUpdateDto.id"),
                    @CacheEvict(value = "noUseCabinetList", allEntries = true)
            }
    )
    public void cabinetUpdate(CabinetAddUpdateDto cabinetAddUpdateDto) {
        Cabinet cabinet = BeanUtil.copyProperties(cabinetAddUpdateDto, Cabinet.class);
        cabinetMapper.updateById(cabinet);
    }

    /**
     * 删除柜机
     */
    @Override
    @CacheEvict(
            value= {
                    "selectCabinetList",
                    "cabinetAllInfo",
                    "cabinetDetail",
                    "noUseCabinetList"
            },
            allEntries = true
    )
    public void cabinetDelete(List<Integer> id) {
        cabinetMapper.deleteBatchIds(id);
    }



    /**
     * 扫码-根据柜机编号查询柜机
     */
    @Override
    public Cabinet getBtCabinetNo(String cabinetNo) {
        return cabinetMapper.selectOne(new LambdaQueryWrapper<Cabinet>().eq(Cabinet::getCabinetNo, cabinetNo));
    }

}
